package idv.arthur.work.validation;

import idv.arthur.work.Widgets;
import idv.arthur.work.strucs.B1S1;
import idv.arthur.work.strucs.ValSer;
import idv.arthur.work.strucs.ValidateHostStruc3;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.net.telnet.TelnetClient;

import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

/**
 * 確認這次要部署的對象
 * 是否都有設定該有的主機
 */ 
public class ValidateHost extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public ValidateHost() {
        super();
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	doPost(request,response);
    }

    static Widgets wid = new Widgets();
    InputStream in = null;
    static PrintStream out = null;
    
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		
		request.setCharacterEncoding( wid.UIcodeSet );
		response.setContentType("application/json");
		response.setCharacterEncoding( wid.UIcodeSet );
		
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		Session session = null;
		ChannelSftp sftp = null;
		String errPars = "}";
		
		String type = request.getParameter("type");					// Batch為批次，Single是單檔
		
		String unChkList[] = null;	//在批次中，未勾選必需排除的
		
		/** 
		 * 部署計畫代號 或 資源群組
		 * 視type而定
		 * 		Batch就是部署計畫代號
		 * 		Single就是 資源群組 
		*/
		String tar = request.getParameter("v_tar");						
		String strSQL = null;
		B1S1 b1s1 = new B1S1();
		
		final String bssId = request.getParameter("bssId");
		String subSysId = request.getParameter("subSysId");	//預設的處理方式是for 手動式部署
		String envId = request.getParameter("envId");
		int deplmainSN = 0;
		ValSer valiServer = new ValSer();
		TelnetClient telnet = new TelnetClient();
		int filePortfolio = Integer.parseInt( request.getParameter("filePortfolio") );	//這次部署的檔案組合，1為有web和nonweb，2為僅有nonweb，3為僅有web
		
		try {
			conn = wid.getConn(true);
			
			if ("Batch".equalsIgnoreCase(type) && wid.isNumeric(tar) ) {
				/*	開始確認web類型的設定	*/
				deplmainSN = Integer.parseInt(tar);
				if ( request.getParameter("unChkList") != null && !"".equalsIgnoreCase( request.getParameter("unChkList") ) ) {
					unChkList = request.getParameter("unChkList").split( wid.splitTokenONE );
				}
				
				if ( filePortfolio==1 || filePortfolio==2 ) {
					strSQL = "SELECT DISTINCT t1.subsysid,t1.squadid FROM mpdeplunitsqu t1,depldetail t2 WHERE t1.deplmainSN=t2.deplmainSN AND t1.depldetailid=t2.depldetailid AND t2.isnonweb='t' AND t1.deplmainSN=?";
					
					if ( unChkList != null  ) {
						for ( int i=0; i < unChkList.length; i++) {
							strSQL += " AND t1.depldetailid<>"+unChkList[i];
						}
					}
					errPars = wid.toJend("deplmainSN", tar );
					ps = conn.prepareStatement(strSQL);
					ps.setInt(1, deplmainSN );
					rs = ps.executeQuery();
					tar = "";	
					while ( rs.next() ) {
						tar += ( wid.splitTokenONE+rs.getString("squadid") );
						subSysId = rs.getString("subsysid");
					}
					tar = tar.substring( wid.splitTokenONE.length(), tar.length() );
				}
			} else if ("Single".equalsIgnoreCase(type) ) {
				if ( filePortfolio==3 ) {
					if ( tar.contains( wid.splitTokenONE ) )	{	//包含splitTokenONE 表示不只一個squad
						String[] tmp = tar.split( wid.splitTokenONE ); 
						for (int i=0; i<tmp.length; i++) {
							tar += ( wid.splitTokenONE+tmp[i] );
						}
						tar = tar.substring( wid.splitTokenONE.length(), tar.length() );
					}
				}
			} else {
				if ( filePortfolio==1 || filePortfolio==2 ) {
					JsonReader reader = new JsonReader( new StringReader( tar ) );
					reader.beginArray();
					tar = "";
					while (reader.hasNext()) {
						reader.beginObject();
						reader.nextName();	//檔名
						reader.nextString();
						reader.nextName();	//版本
						reader.nextString();
						reader.nextName();	//執行方式
						reader.nextString();
						reader.nextName();	//延伸路徑
						reader.nextString();
						reader.nextName();	//SVN路徑
						reader.nextString();
						
						reader.nextName();	//資源群組
						reader.beginArray();
						while (reader.hasNext()) {
							reader.beginObject();
							
							reader.nextName();
							String tmp = reader.nextString();
							if ( !tar.contains(tmp) ) {
								tar += (wid.splitTokenONE+tmp);	
							}
							reader.nextName();	//資源群組名稱
							reader.nextString();
							reader.nextName();	//部署路徑
							reader.nextString();
							
							reader.endObject();
						}
						reader.endArray();
						reader.endObject();
					}
					reader.endArray();
					reader.close();
					
					tar = tar.substring(wid.splitTokenONE.length(), tar.length());
				}
			}
			
			if ( filePortfolio==1 || filePortfolio==3 ) {
				/*	取得 Web Console帳密，要測試是否可以連線 */
				strSQL = "SELECT webconsoleip,loginid,pwd FROM wcl t1, env t2 WHERE t1.webconsolesn=t2.webconsolesn AND t2.envid=?";
				errPars =
						wid.toJend("envid", envId);
				ps = conn.prepareStatement(strSQL);
				ps.setString(1, envId );
				rs = ps.executeQuery();
				rs.next();

				/**	用SFTP的函式庫來驗證帳密是否可用	*/
					
				JSch jsch = new JSch();
	            JSch.setConfig("StrictHostKeyChecking", "no");
	            try {
	            	errPars =
							wid.toJ("loginId", rs.getString("loginid") ) +
							wid.toJ("pwd", rs.getString("pwd") ) +
							wid.toJend("ip", rs.getString("webconsoleip") );
	            	
					session = jsch.getSession( rs.getString("loginid"), rs.getString("webconsoleip") ); session.setPassword( rs.getString("pwd") );
		            session.connect();
		            sftp = (ChannelSftp)  session.openChannel("sftp");
		            sftp.connect();
				} catch (JSchException e) {
					b1s1.setOK(false);
	    			b1s1.setMes( "帳號或密碼有問題" );
				}
	    		if (sftp != null) { if ( sftp.isConnected() ) { 
	    			b1s1.setOK(true);
	    			b1s1.setMes( tar );	//將要去的資源群組存在Mes裡
	    			sftp.disconnect(); 
    			} }
				if ( session != null ) { if ( session.isConnected() ) { session.disconnect(); } }
				
				valiServer.setWeb(b1s1);
			} else {
				b1s1.setOK(true);
			}

			ValidateHostStruc3 vhses = new ValidateHostStruc3();
			if ( filePortfolio==1 || filePortfolio==2 ) {		//1 或 2表示存在 non-web的程式，由 wid.valiEnvHost幫我們檢查是否通過
				vhses = wid.valiEnvHost(conn, ps, rs, bssId, subSysId, envId, tar, true);
			} else {
				vhses.setRes("1111");
			}
			valiServer.setNonWeb( vhses );
			
		} catch ( SQLException e) {
			wid.kem(conn, ps, e, wid.toEType("SQLException")+errPars, wid.isPrint2Console );
		} catch ( Exception e) {
			wid.kem(conn, ps, e, wid.toEType("Exception")+errPars, wid.isPrint2Console );
		}  finally {
			try {
				if ( in != null ) { in.close(); }
				if ( out != null ) { out.close(); }
				if ( telnet != null ) { if ( telnet.isConnected() ) telnet.disconnect(); }
				if ( rs != null ) { rs.close(); }
				if ( ps != null ) { ps.close(); }
				if ( conn != null ) { conn.close(); }
				if (sftp != null) { if ( sftp.isConnected() ) { sftp.disconnect(); } }
				if (session != null) { if ( session.isConnected() ) { session.disconnect(); } }
			} catch ( SQLException e ) {
				System.out.println( wid.errProcess(e) );
			}
		}
		
		response.getWriter().write(new Gson().toJson( valiServer ));
	}
	
	public String readUntil(String pattern) {
        try {
            char lastChar = pattern.charAt(pattern.length() - 1);
            StringBuffer sb = new StringBuffer();
            char ch = (char) in.read();  //read(): 不需要傳任何參數，一次讀取一個 byte data，並以 int 型態傳回資料。若無任何資料可讀，則回傳 -1。
            while (true) {
                System.out.print(ch);
                sb.append(ch);
                if (ch == lastChar) {
                    if (sb.toString().endsWith(pattern)) {
                        return sb.toString();
                    }
                }
                ch = (char) in.read();
            }
        }
        catch (Exception e) {
        	System.out.println( wid.errProcess(e) );
        }
        return null;
    }

    public void write(String value) {
        try {
            out.println(value);
            out.flush();
            System.out.println(value);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
	
}